#pragma once
#include"nocopy.hpp"
#include<sys/types.h>
#include<sys/socket.h>
#include<cerrno>
#include<netinet/in.h>
#include<arpa/inet.h>
#include"Log.hpp"
#include"InetAddr.hpp"

enum{
    SOCKET_ERR = 1,
    BIND_ERR
};

class UdpServer: public nocopy
{
public:
    UdpServer(uint16_t port)
        :_port(port),_sockfd(-1)
    {}

    void Init()
    {
        _sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd < 0)
        {
            log.LogMessage(Fatal,"socket err %d %s\n",errno,strerror(errno));
            exit(SOCKET_ERR);
        }

        log.LogMessage(Debug,"socket success sockfd: %d\n",_sockfd);

        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY;
        socklen_t len = sizeof(local);
        int n = ::bind(_sockfd, (struct sockaddr*)&local,len);
        if(n != 0)
        {
            log.LogMessage(Fatal,"bind err %d %s",errno,strerror(errno));
            exit(BIND_ERR);
        }

        log.LogMessage(Debug,"bind success");
    }

    void Start()
    {
        char receive[1024];
        
        while(true)
        {
            struct sockaddr_in local;
            socklen_t size = sizeof(local);
            ssize_t n =  recvfrom(_sockfd, receive, sizeof(receive)-1,0, (struct sockaddr*)&local,&size);
            if(n  > 0)
            {   
                inetaddr addr(local);

                receive[n] = 0;
                //cout<<"[ "<<addr.PrintDebug()<<" ]#"<< receive <<endl;
                sendto(_sockfd,receive,sizeof(receive),0,(struct sockaddr*)&local,size);
            }

        }
    }

    ~UdpServer()
    {}

private:
    //string _ip;
    uint16_t _port;
    int _sockfd;
};